package com.eastfair.questionnaire.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.eastfair.annotation.model.LoadService;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.utils.CollHelper;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.core.utils.ValidateUtil;
import com.eastfair.projectcore.api.ProjectCoreServiceFeign;
import com.eastfair.core.snowflake.DefaultUidGenerator;
import com.eastfair.questionnaire.dao.QuestionnaireMapper;
import com.eastfair.questionnaire.dto.QuestionnaireDTO;
import com.eastfair.questionnaire.dto.QuestionnaireExcelResultDTO;
import com.eastfair.questionnaire.entity.Questionnaire;
import com.eastfair.questionnaire.service.QuestionService;
import com.eastfair.questionnaire.service.QuestionnaireService;
import com.eastfair.questionnaire.vo.DynamicQuestionnaireVO;
import com.eastfair.questionnaire.vo.QuestionVO;
import com.eastfair.questionnaire.vo.QuestionnaireVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 问卷
 * </p>
 *
 * @author yuwx
 * @date 2021-08-18
 */
@Slf4j
@Service
public class QuestionnaireServiceImpl extends SuperServiceImpl<QuestionnaireMapper, Questionnaire> implements QuestionnaireService, LoadService {

    private ProjectCoreServiceFeign projectCoreServiceFeign;
    private QuestionService questionService;

    @Autowired
    public QuestionnaireServiceImpl(ProjectCoreServiceFeign projectCoreServiceFeign, QuestionService questionService) {
        this.projectCoreServiceFeign = projectCoreServiceFeign;
        this.questionService = questionService;
    }

    /**************sharding 分库分表操作 *****************/
    @Override
    public boolean updateByIdOfShard(Questionnaire entity) {
        UpdateWrapper<Questionnaire> updateWrapper = new UpdateWrapper<>();
        //可将指定字段更新为null
        updateWrapper.lambda().eq(Questionnaire::getProjectId, entity.getProjectId()).eq(Questionnaire::getId, entity.getId())
                .eq(Questionnaire::getIsEnable, BusinessConstant.YES)
                .eq(Questionnaire::getIsDelete, BusinessConstant.NO);
        entity.setProjectId(null);
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(Questionnaire model) {
        //雪花ID
        if (Objects.isNull(model.getId())) {
            model.setId(DefaultUidGenerator.getUidOfProjectId(ContextUtil.getProjectId()));
        }
        model.setProjectId(ContextUtil.getProjectId());
        return R.successDef();
    }

    @Override
    public List<QuestionnaireVO> listAll(Long projectId) {
        if (Objects.isNull(projectId)) {
            return Collections.emptyList();
        }
        QueryWrapper<Questionnaire> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Questionnaire::getProjectId, projectId)
                .eq(Questionnaire::getIsEnable, BusinessConstant.YES)
                .eq(Questionnaire::getIsDelete, BusinessConstant.NO);
        List<Questionnaire> questionnaireList = list(queryWrapper);
        if (CollectionUtil.isEmpty(questionnaireList)) {
            return Collections.emptyList();
        }
        return ConvertUtil.convertList(questionnaireList, QuestionnaireVO.class);
    }

    @Override
    public QuestionnaireVO get(Long projectId, Long id) {
        if (Objects.isNull(id)) {
            return null;
        }
        QueryWrapper<Questionnaire> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Questionnaire::getProjectId, projectId)
                .eq(Questionnaire::getId, id);
        Questionnaire questionnaire = getOne(queryWrapper);
        return BeanUtil.toBean(questionnaire, QuestionnaireVO.class);
    }

    @Override
    public QuestionnaireVO getComplete(Long projectId, Long id) {
        QuestionnaireVO questionnaire = get(projectId, id);
        if (Objects.isNull(questionnaire)) {
            return null;
        }
        List<QuestionVO> questionList = questionService.listWithAnswer(projectId, id);
        questionnaire.setQuestionList(questionList);
        return questionnaire;
    }

    @Override
    public QuestionnaireVO getCompleteWithAnswerResult(Long projectId, Long id, String subjectType, Long subjectId) {
        QuestionnaireVO questionnaire = get(projectId, id);
        if (Objects.isNull(questionnaire)) {
            return null;
        }
        List<QuestionVO> questionList = questionService.listWithAnswer(projectId, id, subjectType, subjectId);
        questionnaire.setQuestionList(questionList);
        return questionnaire;
    }

    @Override
    public DynamicQuestionnaireVO getDynamicWithAnswerResult(Long projectId, Long id, String subjectType, Long subjectId) {
        QuestionnaireVO questionnaire = getCompleteWithAnswerResult(projectId, id, subjectType, subjectId);
        if (Objects.isNull(questionnaire)) {
            return null;
        }
        DynamicQuestionnaireVO dynamicQuestionnaire = BeanUtil.toBean(questionnaire, DynamicQuestionnaireVO.class);
        List<QuestionVO> questionList = questionnaire.getQuestionList();
        if (CollectionUtil.isEmpty(questionList)) {
            return dynamicQuestionnaire;
        }
        dynamicQuestionnaire.setFirstQuestionId(questionList.stream().findFirst().get().getId());
        dynamicQuestionnaire.setQuestionMap(questionList.stream().collect(Collectors.toMap(QuestionVO::getId, QuestionVO -> QuestionVO)));
        return dynamicQuestionnaire;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public QuestionnaireVO save(QuestionnaireDTO questionnaire) {
        if (Objects.isNull(questionnaire)) {
            throw new NullPointerException("questionnaire is null");
        }
        if (!ValidateUtil.validateSimple(questionnaire, QuestionnaireDTO.validateBase.class, QuestionnaireDTO.validateSave.class)) {
            throw new IllegalArgumentException("params is error");
        }
        Questionnaire questionnaireEntity = BeanUtil.toBean(questionnaire, Questionnaire.class);
//        questionnaireEntity.setId(DefaultUidGenerator.getUidOfProjectId(questionnaire.getProjectId()));
        if (!Objects.isNull(questionnaireEntity.getId())) {
            updateByIdOfShard(questionnaireEntity);
        } else {
            save(questionnaireEntity);
        }
        return BeanUtil.toBean(questionnaireEntity, QuestionnaireVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleted(Long projectId, Long id) {
        Questionnaire questionnaire = Questionnaire.builder().projectId(projectId).id(id).isDelete(BusinessConstant.YES).build();
        updateByIdOfShard(questionnaire);
        questionService.deleteByQuestionnaire(projectId, id);
    }

    public void saveImportResult(QuestionnaireExcelResultDTO questionnaireExcelResultDTO) {

    }

    @Override
    public Map<Serializable, Object> findNameByIds(Set<Serializable> set) {
        return null;
    }

    @Override
    public Map<Serializable, Object> findByIds(Set<Serializable> set) {
        List<Questionnaire> questionnaireList = set.stream()
                .map(id -> {
                    QueryWrapper<Questionnaire> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(Questionnaire::getProjectId, ContextUtil.getProjectId())
                            .eq(Questionnaire::getId, id);
                    Questionnaire questionnaire = getOne(queryWrapper);
                    return questionnaire;
                }).collect(Collectors.toList());

        return CollHelper.uniqueIndex(questionnaireList, Questionnaire::getId, Questionnaire::getName);
    }
}
